package cn.sc.summer.core.interceptor;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.NonNull;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 类名：web请求拦截器
 *
 * @author a-xin
 * @date 2023/8/18 17:22
 */
@Slf4j
@Configuration
public class RequestInterceptor implements HandlerInterceptor, DisposableBean {

    private static final ThreadLocal<Long> START_THREAD_LOCAL = new ThreadLocal<>();

    /**
     * 预处理1.程序先执行preHandle()方法，如果该方法的返回值为true，则程序会继续向下执行处理器中的方法，否则将不再向下执行。
     *
     * @param request  current HTTP request 请求体
     * @param response current HTTP response 返回数据
     * @param handler  chosen handler to execute, for type and/or instance evaluation 拦截器
     * @return 是否继续处理
     */
    @Override
    public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) {
        Long startTime = System.currentTimeMillis();
        START_THREAD_LOCAL.set(startTime);
        return true;
    }

    /**
     * 2.在业务处理器（即控制器Controller类）处理完请求后，会执行postHandle()方法，然后会通过DispatcherServlet向客户端返回响应。
     *
     * @param request      current HTTP request
     * @param response     current HTTP response
     * @param handler      the handler that started asynchronous
     *                     execution, for type and/or instance examination
     * @param modelAndView the {@code ModelAndView} that the handler returned
     *                     (can also be {@code null})
     */
    @Override
    public void postHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler, ModelAndView modelAndView) {
        String requestURI = request.getRequestURI();
        Long startTime = START_THREAD_LOCAL.get();
        Long endTime = System.currentTimeMillis();
        long time = endTime - startTime;
        log.debug("<- Http request: {} all time: {} ms", requestURI, time);
    }

    /**
     * 3.在DispatcherServlet处理完请求后，才会执行afterCompletion()方法。
     *
     * @param request  current HTTP request
     * @param response current HTTP response
     * @param handler  the handler that started asynchronous
     *                 execution, for type and/or instance examination
     * @param ex       any exception thrown on handler execution, if any; this does not
     *                 include exceptions that have been handled through an exception resolver
     */
    @Override
    public void afterCompletion(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler, Exception ex) {
    }

    /**
     * Invoked by the containing {@code BeanFactory} on destruction of a bean.
     */
    @Override
    public void destroy() {
        START_THREAD_LOCAL.remove();
    }

}
